home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevm4.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  9.5 KB  |  312 lines

  1. /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevm4.c,v 1.2 2000/09/19 19:00:13 lpd Exp $ */
  20. /* 4-bit-per-pixel "memory" (stored bitmap) device */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gxdevice.h"
  24. #include "gxdevmem.h"        /* semi-public definitions */
  25. #include "gdevmem.h"        /* private definitions */
  26.  
  27. /* ================ Standard (byte-oriented) device ================ */
  28.  
  29. #undef chunk
  30. #define chunk byte
  31. #define fpat(byt) mono_fill_make_pattern(byt)
  32.  
  33. /* Procedures */
  34. declare_mem_procs(mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle);
  35.  
  36. /* The device descriptor. */
  37. const gx_device_memory mem_mapped4_device =
  38. mem_device("image4", 4, 0,
  39.        mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
  40.   mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle,
  41.        mem_gray_strip_copy_rop);
  42.  
  43. /* Convert x coordinate to byte offset in scan line. */
  44. #undef x_to_byte
  45. #define x_to_byte(x) ((x) >> 1)
  46.  
  47. /* Define the 4-bit fill patterns. */
  48. static const mono_fill_chunk tile_patterns[16] =
  49. {fpat(0x00), fpat(0x11), fpat(0x22), fpat(0x33),
  50.  fpat(0x44), fpat(0x55), fpat(0x66), fpat(0x77),
  51.  fpat(0x88), fpat(0x99), fpat(0xaa), fpat(0xbb),
  52.  fpat(0xcc), fpat(0xdd), fpat(0xee), fpat(0xff)
  53. };
  54.  
  55.  
  56. /* Fill a rectangle with a color. */
  57. private int
  58. mem_mapped4_fill_rectangle(gx_device * dev,
  59.                int x, int y, int w, int h, gx_color_index color)
  60. {
  61.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  62.  
  63.     fit_fill(dev, x, y, w, h);
  64.     bits_fill_rectangle(scan_line_base(mdev, y), x << 2, mdev->raster,
  65.             tile_patterns[color], w << 2, h);
  66.     return 0;
  67. }
  68.  
  69. /* Copy a bitmap. */
  70. private int
  71. mem_mapped4_copy_mono(gx_device * dev,
  72.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  73.     int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
  74. {
  75.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  76.     const byte *line;
  77.     declare_scan_ptr(dest);
  78.     byte invert, bb;
  79.  
  80.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  81.     setup_rect(dest);
  82.     line = base + (sourcex >> 3);
  83.     /* Divide into opaque and masked cases. */
  84.     if (one == gx_no_color_index) {
  85.     if (zero == gx_no_color_index)
  86.         return 0;        /* nothing to do */
  87.     invert = 0xff;
  88.     bb = ((byte) zero << 4) | (byte) zero;
  89.     } else if (zero == gx_no_color_index) {
  90.     invert = 0;
  91.     bb = ((byte) one << 4) | (byte) one;
  92.     } else {
  93.     /* Opaque case. */
  94.     int shift = ~(sourcex ^ x) & 1;
  95.     byte oz[4];
  96.  
  97.     oz[0] = (byte)((zero << 4) | zero);
  98.     oz[1] = (byte)((zero << 4) | one);
  99.     oz[2] = (byte)((one << 4) | zero);
  100.     oz[3] = (byte)((one << 4) | one);
  101.     do {
  102.         register byte *dptr = (byte *) dest;
  103.         const byte *sptr = line;
  104.         register uint sbyte = *sptr++;
  105.         register int sbit = ~sourcex & 7;
  106.         int count = w;
  107.  
  108.         /*
  109.          * If the first source bit corresponds to an odd X in the
  110.          * destination, process it now.
  111.          */
  112.         if (x & 1) {
  113.         *dptr = (*dptr & 0xf0) |
  114.             ((sbyte >> sbit) & 1 ? one : zero);
  115.         --count;    /* may now be 0 */
  116.         if (--sbit < 0)
  117.             sbit = 7, sbyte = *sptr++;
  118.         ++dptr;
  119.         }
  120.         /*
  121.          * Now we know the next destination X is even.  We want to
  122.          * process 2 source bits at a time from now on, so set things up
  123.          * properly depending on whether the next source X (bit) is even
  124.          * or odd.  In both even and odd cases, the active source bits
  125.          * are in bits 8..1 of sbyte.
  126.          */
  127.         sbyte <<= shift;
  128.         sbit += shift - 1;
  129.         /*
  130.          * Now bit # sbit+1 is the most significant unprocessed bit
  131.          * in sbyte.  -1 <= sbit <= 7; sbit is odd.
  132.          * Note that if sbit = -1, all of sbyte has been processed.
  133.          *
  134.          * Continue processing pairs of bits in the first source byte.
  135.          */
  136.         while (count >= 2 && sbit >= 0) {
  137.         *dptr++ = oz[(sbyte >> sbit) & 3];
  138.         sbit -= 2, count -= 2;
  139.         }
  140.         /*
  141.          * Now sbit = -1 iff we have processed the entire first source
  142.          * byte.
  143.          *
  144.          * Process full source bytes.
  145.          */
  146.         if (shift) {
  147.         sbyte >>= 1;    /* in case count < 8 */
  148.         for (; count >= 8; dptr += 4, count -= 8) {
  149.             sbyte = *sptr++;
  150.             dptr[0] = oz[sbyte >> 6];
  151.             dptr[1] = oz[(sbyte >> 4) & 3];
  152.             dptr[2] = oz[(sbyte >> 2) & 3];
  153.             dptr[3] = oz[sbyte & 3];
  154.         }
  155.         sbyte <<= 1;
  156.         } else {
  157.         for (; count >= 8; dptr += 4, count -= 8) {
  158.             sbyte = (sbyte << 8) | *sptr++;
  159.             dptr[0] = oz[(sbyte >> 7) & 3];
  160.             dptr[1] = oz[(sbyte >> 5) & 3];
  161.             dptr[2] = oz[(sbyte >> 3) & 3];
  162.             dptr[3] = oz[(sbyte >> 1) & 3];
  163.         }
  164.         }
  165.         if (!count)
  166.         continue;
  167.         /*
  168.          * Process pairs of bits in the final source byte.  Note that
  169.          * if sbit > 0, this is still the first source byte (the
  170.          * full-byte loop wasn't executed).
  171.          */
  172.         if (sbit < 0) {
  173.         sbyte = (sbyte << 8) | (*sptr << shift);
  174.         sbit = 7;
  175.         }
  176.         while (count >= 2) {
  177.         *dptr++ = oz[(sbyte >> sbit) & 3];
  178.         sbit -= 2, count -= 2;
  179.         }
  180.         /*
  181.          * If the final source bit corresponds to an even X value,
  182.          * process it now.
  183.          */
  184.         if (count) {
  185.         *dptr = (*dptr & 0x0f) |
  186.             (((sbyte >> sbit) & 2 ? one : zero) << 4);
  187.         }
  188.     } while ((line += sraster, inc_ptr(dest, draster), --h) > 0);
  189.     return 0;
  190.     }
  191.     /* Masked case. */
  192.     do {
  193.     register byte *dptr = (byte *) dest;
  194.     const byte *sptr = line;
  195.     register int sbyte = *sptr++ ^ invert;
  196.     register int sbit = 0x80 >> (sourcex & 7);
  197.     register byte mask = (x & 1 ? 0x0f : 0xf0);
  198.     int count = w;
  199.  
  200.     do {
  201.         if (sbyte & sbit)
  202.         *dptr = (*dptr & ~mask) | (bb & mask);
  203.         if ((sbit >>= 1) == 0)
  204.         sbit = 0x80, sbyte = *sptr++ ^ invert;
  205.         dptr += (mask = ~mask) >> 7;
  206.     } while (--count > 0);
  207.     line += sraster;
  208.     inc_ptr(dest, draster);
  209.     } while (--h > 0);
  210.     return 0;
  211. }
  212.  
  213. /* Copy a color bitmap. */
  214. private int
  215. mem_mapped4_copy_color(gx_device * dev,
  216.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  217.                int x, int y, int w, int h)
  218. {
  219.     /* Use monobit copy_mono. */
  220.     int code;
  221.  
  222.     /* Patch the width in the device temporarily. */
  223.     dev->width <<= 2;
  224.     code = (*dev_proc(&mem_mono_device, copy_mono))
  225.     (dev, base, sourcex << 2, sraster, id,
  226.      x << 2, y, w << 2, h, (gx_color_index) 0, (gx_color_index) 1);
  227.     /* Restore the correct width. */
  228.     dev->width >>= 2;
  229.     return code;
  230. }
  231.  
  232. /* ================ "Word"-oriented device ================ */
  233.  
  234. /* Note that on a big-endian machine, this is the same as the */
  235. /* standard byte-oriented-device. */
  236.  
  237. #if !arch_is_big_endian
  238.  
  239. /* Procedures */
  240. declare_mem_procs(mem4_word_copy_mono, mem4_word_copy_color, mem4_word_fill_rectangle);
  241.  
  242. /* Here is the device descriptor. */
  243. const gx_device_memory mem_mapped4_word_device =
  244. mem_full_device("image4w", 4, 0, mem_open,
  245.         mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
  246.     mem4_word_copy_mono, mem4_word_copy_color, mem4_word_fill_rectangle,
  247.         gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
  248.         gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
  249.  
  250. /* Fill a rectangle with a color. */
  251. private int
  252. mem4_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
  253.              gx_color_index color)
  254. {
  255.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  256.     byte *base;
  257.     uint raster;
  258.  
  259.     fit_fill(dev, x, y, w, h);
  260.     base = scan_line_base(mdev, y);
  261.     raster = mdev->raster;
  262.     mem_swap_byte_rect(base, raster, x << 2, w << 2, h, true);
  263.     bits_fill_rectangle(base, x << 2, raster,
  264.             tile_patterns[color], w << 2, h);
  265.     mem_swap_byte_rect(base, raster, x << 2, w << 2, h, true);
  266.     return 0;
  267. }
  268.  
  269. /* Copy a bitmap. */
  270. private int
  271. mem4_word_copy_mono(gx_device * dev,
  272.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  273.     int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
  274. {
  275.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  276.     byte *row;
  277.     uint raster;
  278.     bool store;
  279.  
  280.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  281.     row = scan_line_base(mdev, y);
  282.     raster = mdev->raster;
  283.     store = (zero != gx_no_color_index && one != gx_no_color_index);
  284.     mem_swap_byte_rect(row, raster, x << 2, w << 2, h, store);
  285.     mem_mapped4_copy_mono(dev, base, sourcex, sraster, id,
  286.               x, y, w, h, zero, one);
  287.     mem_swap_byte_rect(row, raster, x << 2, w << 2, h, false);
  288.     return 0;
  289. }
  290.  
  291. /* Copy a color bitmap. */
  292. private int
  293. mem4_word_copy_color(gx_device * dev,
  294.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  295.              int x, int y, int w, int h)
  296. {
  297.     int code;
  298.  
  299.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  300.     /* Use monobit copy_mono. */
  301.     /* Patch the width in the device temporarily. */
  302.     dev->width <<= 2;
  303.     code = (*dev_proc(&mem_mono_word_device, copy_mono))
  304.     (dev, base, sourcex << 2, sraster, id,
  305.      x << 2, y, w << 2, h, (gx_color_index) 0, (gx_color_index) 1);
  306.     /* Restore the correct width. */
  307.     dev->width >>= 2;
  308.     return code;
  309. }
  310.  
  311. #endif /* !arch_is_big_endian */
  312.